﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Data.Objects;

namespace WCFServiceWebRole1
{


    public class Service1 : IService1
    {

      


        #region class converters
        private SUser EntityUser_to_SUser(User u)
        {
            SUser user = new SUser()
            {
                UserId = u.userID,
                UserName = u.username,
                Password = u.userPass
            };

            return user;

        }

        private SSpot EntitySpot_to_SSpot(Spot s)
        {
            SSpot spot = new SSpot()
            {
                spotId = s.spotID,
                x_value = s.spot_x_value,
                y_value = s.spot_y_value,
                frontORback = s.frontORback,
                userID = s.userID

            };
            return spot;
        }

        private SSpotImages EntitySpotImages_to_SSpotImages(SpotImage s)
        {
            SSpotImages spotImage = new SSpotImages()
            {
                spotID = s.spotID,
                imageID = s.imageID,
                userID = s.userID
            };

            return spotImage;
        }



       

        private SImage EntityImage_to_SImage(Image i)
        {
            SImage image = new SImage()
            {
                imageId = i.imageID,
                imageUri = i.imageUri,
                datecreated = i.dateCreated,
                Area = i.Area,
                Asymmetry = i.Asymmetry,
                Average_B = i.Average_B,
                Average_G = i.Average_G,
                Average_H = i.Average_H,
                Average_I = i.Average_I,
                Average_R = i.Average_R,
                Average_S = i.Average_S,
                Boundary_irregularity = i.Boundary_irregularity,
                Diameter = i.Diameter,
                Dominant_B = i.Dominant_B,
                Dominant_G = i.Dominant_G,
                Dominant_H = i.Dominant_H,
                Dominant_I = i.Dominant_I,
                Dominant_R = i.Dominant_R,
                Dominant_S = i.Dominant_S,
                Energy = i.Energy,
                Entropy = i.Entropy,
                Homogeneity = i.Homogeneity,
                Inertia = i.Inertia,
                Num_of_subregions = i.Num_of_subregions,
                Num_of_subregion_types = i.Num_of_subregion_types,
                Perimeter = i.Perimeter,
                benign = i.benign


            };
            return image;
        }

        #endregion

        //---------------------------------------------------------------------

        // User


        // if it's new user - returns userId, else - returns -1;
        public int AddUser(string userName, string password)
        {
            int newUser_ID = -1;
            if(lookupUser(userName) == null)   // check if this user doesn't exist already
            {
                // user_counter++;

                using(var context = new spottedEntities())
                {
                    User user = new User()
                  {
                      username = userName,
                      userPass = password,
                      //  userID = user_counter
                  };
                    context.AddToUsers(user);
                    context.SaveChanges();
                    newUser_ID = user.userID;
                }
            }
            return newUser_ID;
        }

        //---------------------------------------------------------------------

        public int LoginUser(string userName, string password)
        {
            string query =
            @"SELECT VALUE User.userID FROM spottedEntities.Users AS User WHERE User.username = @userName 
              AND User.userPass = @userPass";
            ObjectParameter[] parameters = new ObjectParameter[2];
            parameters[0] = new ObjectParameter("username", userName);
            parameters[1] = new ObjectParameter("userPass", password);
            int user_id = -1;
            using(var context = new spottedEntities())
            {
                ObjectQuery<int> results = context.CreateQuery<int>(query, parameters);
                if(results.Count<int>() != 0)
                { user_id = results.First<int>(); }

                
            }
            return user_id;
        }

        //---------------------------------------------------------------------

        public SUser lookupUser(string user_name)
        {

            SUser user = null;
            using(var context = new spottedEntities())
            {
              var  users = context.Users.Where(u => u.username == user_name)/*.FirstOrDefault<User>()*/;
              if(users.Count<User>() != 0) 
              {
                  user = EntityUser_to_SUser(users.FirstOrDefault<User>());
              }             
            }

            return user;
        }


        //---------------------------------------------------------------------

        public string getUserPass(string userName)
        {
            string query = @"SELECT VALUE User.userPass FROM spottedEntities.Users AS User WHERE User.username = @username";
            ObjectParameter parameter = new ObjectParameter("username", userName);

            using(var context = new spottedEntities())
            {
                ObjectQuery<string> pass = context.CreateQuery<string>(query, parameter);
                if(pass.Count<string>() == 1)
                {
                    return pass.First<string>();
                }

                return "";
            }
        }


        //---------------------------------------------------------------------

        // returns true if the change was successful and false otherwise
        public Boolean changePass(string userName, string oldPass, string newPass)
        {
            if(getUserPass(userName).Equals(oldPass))
            {
                using(var context = new spottedEntities())
                {
                    var user = (from user1 in context.Users
                                where user1.username == userName
                                select user1).First();
                    user.userPass = newPass;
                    context.SaveChanges();
                }
                return true;
            }

            return false;
        }



        //================================================================

        // Image



        public int AddImage(string imageURI, DateTime timeCreated,
              double Perimeter, double Area, double Diameter, double Asymmetry, double Boundary_irregularity, double Average_R,
              double Average_G, double Average_B, double Dominant_R, double Dominant_G, double Dominant_B, double Average_S,
              double Average_H, double Average_I, double Dominant_H, double Dominant_S, double Dominant_I, double Entropy,
              double Energy, double Inertia, double Homogeneity, double Number_of_subregions, double Number_of_subregion_types, Boolean benign)
        {
            int newImage_ID = -1;
            using(var context = new spottedEntities())
            {

                Image image = new Image()
                    {
                        imageUri = imageURI,
                        dateCreated = timeCreated,

                        Perimeter = Perimeter,
                        Area = Area,
                        Diameter = Diameter,
                        Asymmetry = Asymmetry,
                        Boundary_irregularity = Boundary_irregularity,
                        Average_R = Average_R,
                        Average_G = Average_G,
                        Average_B = Average_B,
                        Dominant_R = Dominant_R,
                        Dominant_G = Dominant_G,
                        Dominant_B = Dominant_B,
                        Average_S = Average_S,
                        Average_H = Average_H,
                        Average_I = Average_I,
                        Dominant_H = Dominant_H,
                        Dominant_S = Dominant_S,
                        Dominant_I = Dominant_I,
                        Entropy = Entropy,
                        Energy = Energy,
                        Inertia = Inertia,
                        Homogeneity = Homogeneity,
                        Num_of_subregions = Number_of_subregions,
                        Num_of_subregion_types = Number_of_subregion_types,
                        benign = benign


                    };

                context.AddToImages(image);
                context.SaveChanges();
                newImage_ID = image.imageID;

            }

            return newImage_ID;
        }


        //-------------------------------------------------------------


        public void deleteImage(int image_id)
        {
            using(var context = new spottedEntities())
            {
                var image = (from i in context.Images
                             where i.imageID == image_id
                             select i).FirstOrDefault<Image>();
                context.Images.DeleteObject(image);
                context.SaveChanges();
            }

        }

        //-------------------------------------------------------------


        public SImage getAllImageData(int image_ID)
        {           
            using(var context = new spottedEntities())
            {
               var images = context.Images.Where(i => i.imageID == image_ID);
               if(images.Count<Image>() == 0) { return null; }
               else { return EntityImage_to_SImage(images.FirstOrDefault<Image>()); }

            }
            

            
        }

        //-------------------------------------------------------------

        public void changeImageUri(int imageId, string newUri)
        {
            using(var context = new spottedEntities())
            {
                var image = (from image1 in context.Images
                             where image1.imageID == imageId
                             select image1).First();
                image.imageUri = "newUri";
                context.SaveChanges();
            }
        }


        //================================================================

        // Spot

      

       public void AddImageToSpot(int spot_id, int user_id, int image_id)
        {
            using(var context = new spottedEntities())
            {
                SpotImage si = new SpotImage()
                {
                    spotID = spot_id,
                    imageID = image_id,
                    userID = user_id
                };

                context.AddToSpotImages(si);
                context.SaveChanges();
            }
        }

        //-------------------------------------------------------------

        public int AddSpot(int userID, double spot_x, double spot_y, Boolean front_OR_back)
        {
            int newSpot_ID = -1;
            using(var context = new spottedEntities())
            {
                Spot spot = new Spot()
                    {                       
                        userID = userID,                       
                        spot_x_value = spot_x,
                        spot_y_value = spot_y,
                        frontORback = front_OR_back
                    };
                context.AddToSpots(spot);

                context.SaveChanges();
                newSpot_ID = spot.spotID;
            }
            return newSpot_ID;
        }
        


        //-------------------------------------------------------------

        public void deleteSpot(int user_id, int spot_ID)
        {
          
            using(var context = new spottedEntities())
            {
                var spot = (from s in context.Spots
                            where s.spotID == spot_ID && s.userID == user_id
                             select s).FirstOrDefault<Spot>();
                context.Spots.DeleteObject(spot);
                context.SaveChanges();
            }

        }

        //-------------------------------------------------------------

        // returns spot_x_value and spot_y_value
       

        //-------------------------------------------------------------

       
        // returns users spots list
        public List<SSpot> getUserSpots(int user_id)
        {
            List<SSpot> userSpots = new List<SSpot>();
           using(var context = new spottedEntities())
            {
                var spots = context.Spots.Where(s => s.userID == user_id);

                 foreach(Spot s in spots)
                 {
                     userSpots.Add(EntitySpot_to_SSpot(s));
                 }
            }
            return userSpots;
        }



        //-------------------------------------------------------------

      
        //-------------------------------------------------------------
        public Boolean isFrontORBack(int spotID)
        {
            Boolean fOrb = false;
            using(var context = new spottedEntities())
            {
                var spots = context.Spots.Where(s => s.spotID == spotID);
                if(spots.Count<Spot>() != 0)
                {
                    fOrb = spots.FirstOrDefault<Spot>().frontORback;
                }
            }

            return fOrb;
        }
        //-------------------------------------------------------------

        // return list of images ids of some user's spot
        public List<int> getSpotImagesIDs(int user_id, int spot_id)
        {
            /*string query = @"SELECT VALUE Image.imageID FROM spottedEntities.Spots AS Spot, spottedEntities.Images as Image
                           WHERE Spot.userID = @userID AND Spot.spotID = @spotID AND Image.imageID = Spot.imageID";*/
            List<int> ids = new List<int>();
            
            using(var context = new spottedEntities())
            {
                var spots = context.SpotImages.Where(s => s.userID == user_id && s.spotID == spot_id);
                if(spots.Count<SpotImage>() != 0)
                {
                    foreach(SpotImage s in spots)
                    {
                        ids.Add(s.imageID);
                    }
                }
            }

            return ids;
        }

        //-------------------------------------------------------------


        // returns all images (with all it's data) of some user's spot
        public List<SImage> getSpotImages(int user_id, int spot_id)
        {
            List<int> imageIDs = getSpotImagesIDs(user_id, spot_id);
            List<SImage> imagesData = new List<SImage>();

            foreach(int id in imageIDs)
            {
                SImage image = getAllImageData(id);
                if(image != null)
                {
                    imagesData.Add(image);
                }
            }

            return imagesData;
        }
        //-------------------------------------------------------------

        //return all images of user per spot
        public Dictionary<int, List<SImage>> getAllUserImagesPerSpot(int user_id)
        {
            Dictionary<int, List<SImage>> images = new Dictionary<int, List<SImage>>();
            List<SSpot> spots = getUserSpots(user_id);
            List<int> userSpotIds = new List<int>();
            foreach(var s in spots)
            {
                userSpotIds.Add(s.spotId);
            }

            foreach(int spotId in userSpotIds)
            {
                List<SImage> spotImages = getSpotImages(user_id, spotId);
                images.Add(spotId, spotImages);
            }
            return images;
        }

       

    }
}
